package com.xwltz.common.ip;

import cn.hutool.core.io.IoUtil;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import org.lionsoul.ip2region.*;
import org.springframework.core.io.ClassPathResource;

import java.io.File;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.Objects;

/**
 * @description Ip2RegionHelper
 * @information on version 1.0 be created by @xwltz at 2021/11/13 14:09
 */

public class Ip2RegionHelper {
	private static final Log logger = LogFactory.get();

	public static Ip2RegionModel geInfo(String ip) {
		return getInfo(ip, 3);
	}

	public static Ip2RegionModel getInfo(String ip, int algorithm) {
		Ip2RegionModel model = new Ip2RegionModel();
		// 查询算法B-tree, Binary, Memory
		try {
			// 读取本地的ip2region.db文件
			String dbPath = Objects.requireNonNull(Ip2RegionHelper.class.getResource("/data/ip2region.db")).getPath();
			logger.info("Ip2RegionUtil.local.dbPath: {}", dbPath);
			File file = new File(dbPath);

			DbConfig config = new DbConfig();
			DbSearcher searcher;

			// 由于打成jar包后，ip2region.db文件路径发生变化，导致File无法读取，故通过stream流方式复制生成临时的ip2region.db的文件
			if (!file.exists()) {
				ClassPathResource resource = new ClassPathResource("/data/ip2region.db");
				InputStream inputStream = resource.getInputStream();
				byte[] dbBinStr = IoUtil.readBytes(inputStream);
				searcher = new DbSearcher(config, dbBinStr);
			} else {
				searcher = new DbSearcher(config, dbPath);
			}

			// define the method
			Method method;
			switch (algorithm) {
				case DbSearcher.BTREE_ALGORITHM:
					method = searcher.getClass().getMethod("btreeSearch", String.class);
					break;
				case DbSearcher.BINARY_ALGORITHM:
					method = searcher.getClass().getMethod("binarySearch", String.class);
					break;
				default:
					method = searcher.getClass().getMethod("memorySearch", String.class);
					break;
			}

			DataBlock dataBlock;
			if (!Util.isIpAddress(ip)) {
				logger.info("Ip2RegionUtil.getCityInfo.error: Invalid ip address");
			}

			dataBlock = (DataBlock) method.invoke(searcher, ip);
			String cityIpString = dataBlock.getRegion();
			logger.info("Ip2RegionUtil.getCityInfo.cityIpString is {}", cityIpString);
			// 获取城市的信息
			String[] ipStr = cityIpString.split("\\|");
			model.setCountry(ipStr[0]);
			model.setRegion(ipStr[1]);
			model.setProvince(ipStr[2]);
			model.setCity(ipStr[3]);
			model.setIsp(ipStr[4]);
			return model;
		} catch (Exception e) {
			logger.error("Ip2RegionUtil.getCityInfo.error: {}", e);
		}
		return model;
	}
}


